Skip to content

[36/36] Fix request action first-click reliability - #71

Open
cjohnsto-nz wants to merge 5 commits into
feature/oc-160-grpc-demo-server-reliabilityfrom
feature/oc-170-request-action-first-click
Open

[36/36] Fix request action first-click reliability#71
cjohnsto-nz wants to merge 5 commits into
feature/oc-160-grpc-demo-server-reliabilityfrom
feature/oc-170-request-action-first-click

Conversation

@cjohnsto-nz

@cjohnsto-nz cjohnsto-nz commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Summary

Implements OC-170 request-action first-click reliability in the assigned final implementation branch. The original implementation remains at d7047a2, including ad70f83 for the action reliability change and its completion ledger updates.

Review rework ownership

The additional review guard from 03fdf0a is preserved at the stack tip in PR #72 as c303d27. It adds one-dispatch pending guards for HTTP, GraphQL, gRPC, WebSocket lifecycle and message actions, deterministic host-message transitions, focus preservation, propagation-safe activation, and stale click-suppression cleanup.

The full 37-PR sequential composition audit found that retaining 03fdf0a on PR #71 conflicts with review corrections that must also arrive at the final stack tip. Moving it to PR #72 preserves the behavior while keeping this historical branch and its descendants clean.

Stack integrity and validation

@APKiwi

APKiwi commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Verdict: approve with nits. This is a legitimate mechanism fix, not a mask: buttons render disabled until hydration reaches ready (the gate is deterministic, dispatch is impossible before requestLoaded flips state), and activation moves to capture-phase mousedown which precedes the webview focus-swallowed click. No retries or delays. One honest caveat the ledger itself makes: JSDOM can't reproduce the VS Code focus behavior, so the tests validate the mechanism and the actual root-cause theory is settled by manual smoke, belt-and-suspenders is acceptable here.

  • Minor: residual double-dispatch window. activatePrimaryRequestAction branches on isSending, which only flips when the host echoes sending, so two fast activations before the echo both post sendRequest. Pre-existing logic, but the task explicitly demanded single-shot dispatch and this PR adds no client-side in-flight guard. A local pending flag closes it.
  • Nit: preventDefault on mousedown suppresses button focus after mouse activation, focus stays in the editor. Likely intended, it is a behavior change from native click.
  • Nit: capture-phase stopPropagation can starve ancestor handlers (an outside-click closer would no longer see a Send click). Low impact.
  • Nit: a mousedown-then-drag-off leaves suppressNextClick stale. Verified benign, there's no programmatic .click() on the main send button (the :2113 click targets the modal's local button) and the next real click self-heals via its own mousedown. Just noting the flag isn't reset on mouseup/leave.

Tests: mostly non-tautological and would fail against the old click-only wiring: disabled during hydration asserted, activation fires on mousedown post-hydration with exactly one sendRequest, suppressed follow-click proven, keyboard Enter/Space covered, WS connect/send/disconnect first-click covered, and the GraphQL case proves the first activation posts the freshly-edited model. Weakness: the command/toolbar/CodeLens route test is a static manifest assertion that passes regardless of the fix.

Deps: none added.

@cjohnsto-nz

Copy link
Copy Markdown
Owner Author

Addressed every actionable point in 03fdf0a.

  • Residual double dispatch: fixed. Local pending guards are set before posting to the host, so rapid mouse, keyboard, and shortcut activations cannot dispatch twice while waiting for sending, WebSocket lifecycle state, cancellation, response, or error acknowledgement. This covers HTTP, GraphQL, gRPC, WebSocket connect/disconnect, and WebSocket message send.
  • Mouse focus: fixed. Capture-phase mousedown now explicitly focuses the activated button before preventing the focus-swallowed native click path.
  • Event propagation: fixed. stopPropagation was removed. Mounted tests prove document-level mousedown and click listeners still observe the action.
  • Stale click suppression: fixed. A document mouseup outside the button clears suppression, and a zero-delay fallback clears it when pending state disables the button before a native click can follow.
  • Static command/toolbar/CodeLens test: it remains a route-registration contract only; it is not being used as behavioral proof of this fix. The mounted JSDOM tests are the behavioral proof: rapid duplicate attempts dispatch exactly once, pending state is visible until host acknowledgement, mouse focus is retained, ancestor handlers receive the event, abandoned activation resets cleanly, and keyboard activation follows the same guard.

Validation passed: focused layout/WebSocket 56 tests, affected feature suite 122 tests, full suite 496 tests, demo validation 47/47, TypeScript compile, extension build, and all GitHub build/security checks.

Stack integrity was checked before the push. Updated PR 70 -> PR 71 and PR 71 -> PR 72 both merged cleanly in three-way simulation. GitHub now reports PR 71 and PR 72 as MERGEABLE/CLEAN.

@cjohnsto-nz
cjohnsto-nz force-pushed the feature/oc-170-request-action-first-click branch from 03fdf0a to d7047a2 Compare July 21, 2026 22:07
@cjohnsto-nz

Copy link
Copy Markdown
Owner Author

Correction to my earlier response: the review guard is no longer owned by this historical branch.

The guard from 03fdf0a remains fully delivered at the stack tip in PR #72 as c303d27. The 37-PR sequential audit showed that retaining it on PR #71 conflicts with other required review corrections at final composition, so PR #71 is restored to its assigned OC-170 implementation head d7047a2.

Verified final state:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants